function Metro(e){var m=this;this.elemMetro=document.getElementById(e),this.Lines=new Array,this.camera=new function(){var s=this,n=30,i=new Number,a=(new Array,0),r=new Number,o=new Number,h=new Number,l=new Number;this.setScreen=function(){var e=m.elemMetro.offsetWidth,t=m.elemMetro.offsetHeight;o=Math.min(e,t),h=e/2,l=t/2,i=o/2/Math.tan(n/180*Math.PI/2)},this.setDefaultViewDistance=function(){r=11/Math.tan(n/180*Math.PI/2)},this.setDefaultAverageHeight=function(){for(var e=a=0,t=0;t<m.Lines.length;t++)for(var n=0;n<m.Lines[t].Stations.length;n++)a+=m.Lines[t].Stations[n].Coords[2],e++;0<e&&(a/=e)},this.setViewDistance=function(e){isNaN(e)?s.setDefaultViewDistance():(e<0&&(e=0),r=e)},this.getViewDistance=function(){return r},this.multiplyViewDistance=function(e){r*=e},this.setAngles=function(e,t){var n=s;isNaN(e)&&(e=-90),isNaN(t)&&(t=45),t=Math.max(Math.min(t,90),-90),n.phi=e,n.theta=t,e=e/180*Math.PI,t=t/180*Math.PI;var i=Math.cos(e),a=Math.sin(e),e=Math.cos(t),t=Math.sin(t);n.viewMatrix=[[-a,i,0],[-t*i,-t*a,e],[e*i,e*a,t]]},this.getAngles=function(){return{phi:s.phi,theta:s.theta}},this.addAngles=function(e,t){s.setAngles(s.phi+e,s.theta+t)},this.applyMatrix=function(e){return[s.viewMatrix[0][0]*e[0]+s.viewMatrix[0][1]*e[1]+s.viewMatrix[0][2]*e[2],s.viewMatrix[1][0]*e[0]+s.viewMatrix[1][1]*e[1]+s.viewMatrix[1][2]*e[2],s.viewMatrix[2][0]*e[0]+s.viewMatrix[2][1]*e[1]+s.viewMatrix[2][2]*e[2]]},this.calcView=function(e){var t=s;return(e=[e[0],e[1],e[2]])[2]-=a,(e=t.applyMatrix(e))[2]-=r,e[2]=0<e[2]?-1e-6:e[2],t=-e[2]/i,[h+e[0]/t,l-e[1]/t,e[2]]},this.optimizeSizeToScreen=function(e){return Math.min(e/750*o,e)},this.emulateVisibleSize=function(e){return(e+=r)<-5?.8:5<e?5/4:(1-(e=(e+5)/10))/(5/4)+5/4*e},this.getMetersPerCm=function(e){return[e=r/i*e/2.54*1e3,e/m.geo.getDepthScale()]},this.setScreen(),this.setDefaultViewDistance(),this.setAngles(-90,45)},this.geo=new function(){var n=this,i=55.755793*Math.PI/180,a=37.617678*Math.PI/180,s=1;this.getDepthScale=function(){return 50},this.getShowTerrain=function(){return s},this.setShowTerrain=function(e){s=0==e?0:1},this.thetaPhi2XY=function(e,t){return e=e*Math.PI/180,t=t*Math.PI/180,[6371.21*Math.cos(e)*(t-a),6371.21*(e-i)]},this.geoCoords2XYZ=function(e){var t=n.thetaPhi2XY(e[0],e[1]);return t.push(50*(e[2]+e[3]*s)/1e3),t}},this.filter=new function(){var n=this,t=(new Date).getFullYear(),i=t;this.filterYears=!0,this.getSelectedYear=function(){return i},this.getCurrentYear=function(){return t},this.setSelectedYear=function(e){1935<=(e=parseInt(e))&&e<=t&&(i=e)},this.isStationDisplayed=function(e){if(!n.filterYears)return!0;for(var t=e.NamesYears.length-1;0<=t;t--)if(e.NamesYears[t][1]<=i)return void 0===e.NamesYears[t][2]||e.NamesYears[t][2]>i;return!1},this.isTunnelDisplayed=function(e){return n.isStationDisplayed(e.station1)&&n.isStationDisplayed(e.station2)},this.checkLine=function(e){for(var t=e,n=[],i=1;i<t.Stations.length-1;i++)(t.Stations[i-1].isHidden()||!t.Stations[i].isHidden()||t.Stations[i+1].isHidden())&&("Молодежная"!=t.Stations[i].getName()&&"Molodyozhnaya"!=t.Stations[i].getName()||t.Stations[i].isHidden())||n.push(t.Stations[i]);if(0<n.length)for(var a=0;a<n.length;a++)for(i=0;i<t.Tunnels.length;i++)(t.Tunnels[i].station1==n[a]||t.Tunnels[i].station2==n[a]&&"Молодежная"!=n[a].getName()&&"Molodyozhnaya"!=n[a].getName())&&"Деловой центр, КСЛ"!=n[a].getName()&&"Delovoy Tsentr, KSL"!=n[a].getName()&&t.Tunnels[i].show()}},this.draw=function(){for(var e=m,t=0;t<e.Lines.length;t++)e.Lines[t].draw()},this.applyFilter=function(){for(var e=m,t=0;t<e.Lines.length;t++)e.Lines[t].applyFilter()},this.rotate=function(e,t){var n=m;return n.camera.addAngles(e,t),n.draw(),!1},this.zoom=function(e){var t=m;return t.camera.multiplyViewDistance(e),t.draw(),!1},this.updateSize=function(){var e=m;return e.camera.setScreen(),e.draw(),!1},this.addLine=function(e,t,n){var i=m,n=new h(n);n.addStations(e,t),i.Lines.push(n),i.camera.setDefaultAverageHeight()},this.setInterchanges=function(e){for(var t=m,n=new h("interchanges"),i=0;i<e.length;i++){var a=null,s=null;e:for(var r=0;r<t.Lines.length;r++)for(var o=0;o<t.Lines[r].Stations.length;o++)if(t.Lines[r].Stations[o].getName()==e[i][0]&&(a=t.Lines[r].Stations[o]),t.Lines[r].Stations[o].getName()==e[i][1]&&(s=t.Lines[r].Stations[o]),a&&s)break e;a&&s&&(n.addTunnel(a,s),Math.sqrt(Math.pow(a.Coords[0]-s.Coords[0],2)+Math.pow(a.Coords[1]-s.Coords[1],2)+Math.pow(a.Coords[2]-s.Coords[2],2))<.1&&(t.camera.calcView(s.Coords)[2]>t.camera.calcView(a.Coords)[2]?a.elemStation.style.paddingTop="8px":s.elemStation.style.paddingTop="8px"))}t.Lines.push(n)},this.inputGetParams=function(){var e=m,t=readGetParams(),n=e.camera.getAngles(),i=e.camera.getViewDistance(),a=e.filter.getSelectedYear();t.p&&(n.phi=Number(t.p));t.t&&(n.theta=Number(t.t));t.d&&(i=Number(t.d));t.y&&(a=Number(t.y));e.camera.setAngles(n.phi,n.theta),e.camera.setViewDistance(i),e.filter.setSelectedYear(a)},this.outputGetParams=function(){var e=m,t={p:e.camera.getAngles().phi,t:e.camera.getAngles().theta,d:e.camera.getViewDistance()};e.filter.getSelectedYear()!=e.filter.getCurrentYear()?t.y=e.filter.getSelectedYear():t.y="";writeGetParams(t)},this.useGPU=!1;var o=parseInt(getCssValue("#metro ul span","height")),p=parseInt(getCssValue("#metro ul span","marginTop")),f=1==parseInt(decodeURI(readGetParams().en));function h(e){var a=this;this.elemLine=document.createElement("ul"),this.Stations=new Array,this.Tunnels=new Array,this.lineId=e,this.draw=function(){for(var e=a,t=0;t<e.Stations.length;t++)e.Stations[t].draw();for(t=0;t<e.Tunnels.length;t++)e.Tunnels[t].draw()},this.applyFilter=function(){for(var e=a,t=0;t<e.Stations.length;t++)e.Stations[t].applyFilter();for(t=0;t<e.Tunnels.length;t++)e.Tunnels[t].applyFilter();m.filter.checkLine(e)},this.addStations=function(e,t){for(var n=a,i=0;i<e.length;i++)n.Stations.push(new s(e[i],t[i])),0<i&&n.Tunnels.push(new r(n.Stations[i-1],n.Stations[i]))},this.addTunnel=function(e,t){a.Tunnels.push(new r(e,t))};var n=parseInt(getCssValue("#"+a.lineId+" span","height")),i=parseInt(getCssValue("#"+a.lineId+" span","marginTop"));function s(e,t){var s=this;this.NamesYears=t,this.elemStation=document.createElement("li"),this.geoCoords=e,this.Coords=m.geo.geoCoords2XYZ(e),this.renderedCoords,this.lastRenderedCoords,this.getYear=function(){return s.NamesYears[0][1]},this.getName=function(e){if(void 0===e)return s.NamesYears[s.NamesYears.length-1][0];for(var t=s.NamesYears.length-1;0<=t;t--)if(s.NamesYears[t][1]<=e&&(void 0===s.NamesYears[t][2]||s.NamesYears[t][2]>e))return s.NamesYears[t][0];return""},this.show=function(){s.elemStation.style.display=""},this.hide=function(){s.elemStation.style.display="none"},this.isHidden=function(){return"none"==s.elemStation.style.display},this.makeDescription=function(e){var t=s;t.elemStation.innerHTML=t.getName(e),t.elemStation.setAttribute("data-tooltip","<b>"+t.getName(e)+"</b> ("+t.getYear()+(f?")<br>":" г.)<br>")+(f?"Coordinates: ":"Координаты: ")+Math.round(10*t.Coords[0])/10+(f?" km, ":" км, ")+Math.round(10*t.Coords[1])/10+(f?" km<br>":" км<br>")+(f?"Depth: ":"Глубина: ")+(0<t.geoCoords[2]?"+":"")+t.geoCoords[2]+(f?" m (":" м (")+(t.geoCoords[2]+t.geoCoords[3])+(f?" above sea level)":" над ур. моря)")+"<br><span>"+(f?"(Click to select a line)":"(Кликните для выделения линии)")+"</span>")},this.applyFilter=function(){var e=s;m.filter.isStationDisplayed(e)?(e.show(),e.makeDescription(m.filter.getSelectedYear())):e.hide()},this.draw=function(){var e=s;e.lastRenderedCoords=e.renderedCoords,e.renderedCoords=m.camera.calcView(e.Coords);var t=m.camera.emulateVisibleSize(e.renderedCoords[2]),n=t*m.camera.optimizeSizeToScreen(12),i="",a="";m.useGPU&&(i="translate("+e.renderedCoords[0]+"px, "+e.renderedCoords[1]+"px)",a=" scale("+n/m.camera.optimizeSizeToScreen(12)+")");e.elemStation.style.cssText=(m.useGPU?"-ms-transform:"+i+a+";-webkit-transform:"+i+a+";-moz-transform:"+i+a+";-o-transform:"+i+a+";transform:"+i+a+";":"left:"+e.renderedCoords[0]+"px;top:"+e.renderedCoords[1]+"px;line-height:"+n+"px;background-size:"+n+"px;margin:"+-n/2+"px 0 0 "+-n/2+"px;")+"z-index:"+Math.round(100*(e.renderedCoords[2]+m.camera.getViewDistance()+30))+";opacity:"+Math.min(1,.9*t)+";display:"+e.elemStation.style.display+";padding-top:"+e.elemStation.style.paddingTop+";"},this.applyFilter(),a.elemLine.appendChild(this.elemStation)}function r(e,t){var h,l=this,d=n||o,u=i||p,c=0;this.station1=e,this.station2=t,this.elemTunnel=document.createElement("span"),this.show=function(){l.elemTunnel.style.display=""},this.hide=function(){l.elemTunnel.style.display="none"},this.isHidden=function(){return"none"==l.elemTunnel.style.display},this.applyFilter=function(){var e=l;m.filter.isTunnelDisplayed(e)?e.show():e.hide()},this.draw=function(){var e=l,t=function(e){var t=e.station1.renderedCoords[0],n=e.station1.renderedCoords[1],i=e.station2.renderedCoords[0]-e.station1.renderedCoords[0],a=e.station2.renderedCoords[1]-e.station1.renderedCoords[1];if(0==i&&0==a)return{x1:t,y1:n,x2:t,y2:n};r=Math.abs(i)>Math.abs(a)?(s=(-8e3-t)/i,(8e3-t)/i):(s=(-8e3-n)/a,(8e3-n)/a);var e=Math.min(s,r),s=Math.max(s,r),r=Math.max(0,e),s=Math.min(1,s);return r<s?{x1:t+r*i,y1:n+r*a,x2:t+s*i,y2:n+s*a}:{x1:t+e*i,y1:n+e*a,x2:t+e*i,y2:n+e*a}}(e),n=t.x2-t.x1,i=t.y2-t.y1,a=Math.sqrt(Math.pow(n,2)+Math.pow(i,2)),s=Math.atan2(i,n)/Math.PI*180;s=function(e){e+=c,null!=h&&(180<e-h&&(e-=360,c-=360),e-h<-180&&(e+=360,c+=360));return e}(s),h=s;var r=Math.min(e.station1.renderedCoords[2],e.station2.renderedCoords[2]),o=(e.station1.renderedCoords[2]+e.station2.renderedCoords[2])/2,i=m.camera.emulateVisibleSize(o),n=" rotate("+s+"deg)",o="",s="";m.useGPU&&(o="translate("+t.x1+"px, "+t.y1+"px)",s=" scaleY("+i+")");e.elemTunnel.style.cssText=(m.useGPU?"":"left:"+t.x1+"px;top:"+t.y1+"px;height:"+i*m.camera.optimizeSizeToScreen(d)+"px;margin-top:"+i*m.camera.optimizeSizeToScreen(u)+"px;")+"width:"+a+"px;z-index:"+Math.round(100*(r+m.camera.getViewDistance()+30)-1)+";opacity:"+Math.min(1,.9*i)+";-ms-transform:"+o+n+s+";-webkit-transform:"+o+n+s+";-moz-transform:"+o+n+s+";-o-transform:"+o+n+s+";transform:"+o+n+s+";display:"+e.elemTunnel.style.display+";"},this.elemTunnel.setAttribute("data-tooltip",(f?"Distance: ":"Расстояние: ")+Math.round(10*Math.sqrt(Math.pow(this.station2.Coords[0]-this.station1.Coords[0],2)+Math.pow(this.station2.Coords[1]-this.station1.Coords[1],2)+Math.pow((this.station2.Coords[2]-this.station1.Coords[2])/m.geo.getDepthScale(),2)))/10+(f?" km<br>":" км<br>")+(f?"Height difference: ":"Перепад высот: ")+Math.round(Math.abs(this.station2.Coords[2]-this.station1.Coords[2])/m.geo.getDepthScale()*1e3)+(f?" m":" м")+"<br><span>"+(f?"(Click to select a line)":"(Кликните для выделения линии)")+"</span>"),a.elemLine.appendChild(this.elemTunnel)}this.elemLine.id=e,m.elemMetro.appendChild(this.elemLine)}}